#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "peer.h"
#include "tad.h"
#include "tracker_thread.h"

/* VAR GLOBALES */
extern struct peer *hashmap_peers;
extern struct file *hashmap_sfiles;
extern struct file *hashmap_lfiles;
extern pthread_t peers[NUM_MAX_PEERS];
extern pthread_t tracker;
extern char tracker_ip[];
extern int tracker_port;
extern int listening_port;
extern int tracker_socket;
extern int update_delay;
pthread_mutex_t tracker_mutex;


void getfile(char *key) {
  char tpcmd[BUF_SIZE];
  pthread_mutex_lock (&tracker_mutex);
  printf("Getting file %s...\n", key);
  
  sprintf(tpcmd, "getfile %s ", key);
  write(tracker_socket, tpcmd, strlen(tpcmd));
  pthread_mutex_unlock (&tracker_mutex);
}

char tpbuff[BUF_SIZE], tpcmd[BUF_SIZE];
int tpready=0, tpreadc, tpoffset=0;


void peers_rcvd(void) { // If "peers" received
    char *ip = NULL, *port=NULL;
  
    READ(tracker_socket, tpbuff, tpready, tpreadc, tpoffset); // Clé
    char *key = strdup(tpbuff);
    READ(tracker_socket, tpbuff, tpready, tpreadc, tpoffset); // [
    int num = 0;
    
    while(1) {
      if(ip) { free(ip); ip = NULL; }
      if(port) { free(port); port = NULL; }
      READ(tracker_socket, tpbuff, tpready, tpreadc, tpoffset); // IP
      if(!strcmp(tpbuff, "]"))
        break;
      ip = strdup(tpbuff);
      READ(tracker_socket, tpbuff, tpready, tpreadc, tpoffset);  // lecture de :
      READ(tracker_socket, tpbuff, tpready, tpreadc, tpoffset); // port
      port = strdup(tpbuff);
      connect_and_ask(ip, port, key);
      num++;
    } 
    if(!num) printf("No peer found\n");
    
    if(ip) { free(ip); ip = NULL; }
    if(port) { free(port); port = NULL; }
}

extern int gargc;
extern char **gargv;

void *tracker_thread(void *peer) {
  //int id = *((int *)peer);
  //struct peer *p = peer;

  printf("Entered in tracker thread !\n");
  tpbuff[0] = '\0';
  
  struct sockaddr_in serverSockAddr;
  long hostAddr;
  
  bzero(&serverSockAddr , sizeof(serverSockAddr));
  hostAddr = inet_addr(tracker_ip);
  
  if ((long)hostAddr != (long)-1)
    bcopy(&hostAddr,&serverSockAddr.sin_addr,sizeof(hostAddr));
  else {
      printf("Couldn't connect to tracker\n");
      exit(0);
  }
  
  serverSockAddr.sin_port = htons(tracker_port);
  serverSockAddr.sin_family = AF_INET;


  if ((tracker_socket = socket(AF_INET,SOCK_STREAM,0)) < 0)
  {
    perror("Couldn't connect to tracker");
    exit(0);
  }

  if(connect(tracker_socket, (struct sockaddr *)&serverSockAddr, sizeof(serverSockAddr)) < 0)
  {
    perror("Couldn't connect to tracker (connect)");
    exit(0);
  }
  pthread_mutex_unlock (&tracker_mutex); // Initialisation terminée
  
  announce();

  while(1) {
      READ(tracker_socket, tpbuff, tpready, tpreadc, tpoffset); 
  
      if(!strcmp(tpbuff, "quit"))
        break;
        
      else if(!strcmp(tpbuff, "ok"))
        printf("command successful\n");
        
      else if(!strcmp(tpbuff, "peers")) {
        printf("received peers\n");
        peers_rcvd();
      }
      
      
/*     if(gargc>2 && atoi(gargv[2])) {
        getfile("8905e92afeb80fc7722ec89eb0bf0966"); gargc=0; }*/
        printf("Please enter a file ID:\n");
        scanf("%s", tpcmd);
        if(tpcmd[0]!='\0')
          getfile(tpcmd);
  };

  close(tracker_socket);
  
  printf("Thread tracker is exiting\n");
  return NULL;
}

